package org.wt.phoenix.middleware.shardingsphere.mockroute.route.handler;

import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
import org.apache.shardingsphere.core.yaml.config.sharding.YamlTableRuleConfiguration;
import org.apache.shardingsphere.core.yaml.config.sharding.strategy.YamlComplexShardingStrategyConfiguration;
import org.wt.phoenix.middleware.shardingsphere.mockroute.domain.HandlerContext;
import org.wt.phoenix.middleware.shardingsphere.mockroute.domain.enums.OperateTypeEnum;

import java.lang.reflect.Method;
import java.util.*;

public class ComplexShardingStrategyHandler implements ShardingStrategyHandler{
    @Override
    public String handler(HandlerContext context) {
        YamlComplexShardingStrategyConfiguration complexStrategy = (YamlComplexShardingStrategyConfiguration) context.getStrategyConfiguration();
        List<String> columns = new ArrayList(Arrays.asList(complexStrategy.getShardingColumns().split(",")));

        if (!columns.contains(context.getColumn())){
            throw new RuntimeException("不支持的列名:" + context.getColumn() + ",分表列为：" + columns);
        }

        String algorithmClassName = complexStrategy.getAlgorithmClassName();
        try {
            Class<?> clazz = Class.forName(algorithmClassName);
            Object strategy = clazz.newInstance();
            Method doShardingMethod = clazz.getMethod("doSharding", Collection.class, ComplexKeysShardingValue.class);

            Collection dataNodes = getDataNodes(context);

            Map<String, Collection> columnNameAndShardingValuesMap = new HashMap();
            columnNameAndShardingValuesMap.put(context.getColumn(), Arrays.asList(context.getShardingValue()));

            ComplexKeysShardingValue value = new ComplexKeysShardingValue(context.getRuleConfiguration().getLogicTable(), columnNameAndShardingValuesMap, Collections.EMPTY_MAP);

            Collection result = (Collection) doShardingMethod.invoke(strategy, dataNodes, value);

            return (String) result.iterator().next();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private Collection getDataNodes(HandlerContext context){
        YamlTableRuleConfiguration ruleConfiguration = context.getRuleConfiguration();
        String actualExpression = ruleConfiguration.getActualDataNodes();
        if (OperateTypeEnum.DATABASE.equals(context.getOperateTypeEnum())){
            int databaseLastIndex = actualExpression.indexOf("}");
            String dbExpression = actualExpression.substring(0, databaseLastIndex + 1);
            int leftIndex = dbExpression.indexOf("{");
            String rangeStr = dbExpression.substring(leftIndex + 1, dbExpression.length() - 1);
            String logicDbName = dbExpression.split("\\$")[0];
            return getDataNodes(logicDbName, rangeStr);

        }else if (OperateTypeEnum.TABLE.equals(context.getOperateTypeEnum())){
            int tableLastIndex = actualExpression.lastIndexOf("}");
            int databaseLastIndex = actualExpression.indexOf("}");

            String tableExpression = actualExpression.substring(databaseLastIndex + 2, tableLastIndex + 1);
            int leftIndex = tableExpression.indexOf("{");
            String rangeStr = tableExpression.substring(leftIndex + 1, tableExpression.length() - 1);
            String logicTableName = tableExpression.split("\\$")[0];
            return getDataNodes(logicTableName, rangeStr);

        }
        throw new RuntimeException("不支持的操作类型");
    }

    private Collection getDataNodes(String logicName, String rangeStr){
        String[] split = rangeStr.split("\\.\\.");
        Long start = Long.valueOf(split[0]);
        Long end = Long.valueOf(split[1]);

        Collection result = new ArrayList();
        for (long i = start; i <= end; i++){
            result.add(logicName + i);
        }
        return result;
    }
}
